#include "surbasic/FileKeys.h"

#include "surbasic/AESHelper.h"
#include "surbasic/Base64Helper.h"

using namespace SDBasic::bytearray;
using namespace SDBasic::base64;
using namespace SDBasic::aes;

namespace SDBasic {

static ByteArray GenShareKeyEncryptKey(const std::string& sha512) {
  ByteArray sharekey_enc_key;
  ByteArray bin = ByteArray::fromHexStr(sha512);
  sharekey_enc_key.insert(sharekey_enc_key.end(), bin.begin() + 16,
                          bin.begin() + 32);
  sharekey_enc_key.insert(sharekey_enc_key.end(), bin.begin() + 48, bin.end());
  return sharekey_enc_key;
}

std::string GeneratePersonalKey(ecc::EciesHelper* ecc,
                                const std::string& storage_key) {
  ByteArray key = ByteArray::fromHexStr(storage_key);
  std::string base64_storage_key = Base64Helper::Encode(key);
  const ByteArray plain = ByteArray::fromRawStr(base64_storage_key);
  ByteArray cipher;
  ecc->Encrypt(plain, cipher);
  return cipher.toUrlBase64Str();
}

std::string EncryptStorageKeyToShareKey(const std::string& sha512,
                                        const std::string& storage_key) {
  ByteArray key = ByteArray::fromHexStr(storage_key);
  std::string base64_storage_key = Base64Helper::Encode(key);

  ByteArray share_enc_key = GenShareKeyEncryptKey(sha512);
  ByteArray out = AESHelper::Encrypt256(
      share_enc_key, ByteArray::fromRawStr(base64_storage_key));
  return out.toUrlBase64Str();
}

bool DecryptStorageKeyFromShareKey(const std::string& share_key,
                                   const std::string& sha512,
                                   std::string* storage_key,
                                   std::string* errmsg) {
  ByteArray storage_key_cipher;
  if (!UrlBase64Helper::Decode(share_key, storage_key_cipher)) {
    *errmsg = "can not url64decode share_key to get storage_key_cipher";
    return false;
  }

  ByteArray share_enc_key = GenShareKeyEncryptKey(sha512);
  ByteArray base64_storage_key =
      AESHelper::Decrypt256(share_enc_key, storage_key_cipher);

  if (base64_storage_key.size() != 44) {
    *errmsg = "base64_storage_key should be 44 bytes";
    return false;
  }

  ByteArray key;
  if (!Base64Helper::Decode(base64_storage_key, key)) {
    *errmsg = "base64_storage_key is not valid base64-encoded string";
    return false;
  }

  if (key.size() != 32) {
    *errmsg = "key should be 32 bytes";
    return false;
  }

  *storage_key = key.toHexStr();
  return true;
}
}
